package com.example.pceb.component;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
//import com.MessageVo;
import com.example.pceb.common.MessageVo;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

//import javax.websocket.*;
//import javax.websocket.server.PathParam;
//import javax.websocket.server.ServerEndpoint;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * WebSocket的操作类
 */
@Component
@Slf4j
@ServerEndpoint("/websocket/{name}")
public class WebSocketServer {

//静态变量，用来记录当前在线连接数，线程安全的类。
    private static final AtomicInteger onlineSessionClientCount = new AtomicInteger(0);

    //存放所有在线的客户端
    private static final Map<String, Session> onlineSessionClientMap = new ConcurrentHashMap<>();

    /**
     * 连接 name 和连接会话
     */
    private String name;

    @OnOpen
    public void onOpen(@PathParam("name") String name, Session session) {
        /**
         * session.getId()：当前session会话会自动生成一个id，从0开始累加的。
         */
        Session beforeSession = onlineSessionClientMap.get(name);
        if (beforeSession != null) {
            //在线数减1
            onlineSessionClientCount.decrementAndGet();
            log.info("连接已存在，关闭之前的连接 ==> session_id = {}， name = {}。", beforeSession.getId(), name);
            //通知之前其他地方连接被挤掉
            sendToOne(name, "您的账号在其他地方登录，您被迫下线。");
            // 从 Map中移除
            onlineSessionClientMap.remove(name);
            //关闭之前的连接
            try {
                beforeSession.close();
            } catch (Exception e) {
                log.error("关闭之前的连接异常，异常信息为：{}", e.getMessage());
            }
        }
        log.info("连接建立中 ==> session_id = {}， name = {}", session.getId(), name);
        onlineSessionClientMap.put(name, session);

        //在线数加1
        onlineSessionClientCount.incrementAndGet();
        this.name = name;
       // sendToOne(name, "连接成功");
        log.info("连接建立成功，当前在线数为：{} ==> 开始监听新连接：session_id = {}， name = {}。", onlineSessionClientCount, session.getId(), name);
    }


    @OnClose
    public void onClose(@PathParam("name") String name, Session session) {
        if (name == null || name.equals("")) {
            name = this.name;
        }
        // 从 Map中移除
        onlineSessionClientMap.remove(name);

        //在线数减1
        onlineSessionClientCount.decrementAndGet();
        log.info("连接关闭成功，当前在线数为：{} ==> 关闭该连接信息：session_id = {}， name = {}。", onlineSessionClientCount, session.getId(), name);
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        JSONObject jsonObject = JSON.parseObject(message);
        String toname = jsonObject.getString("name");
        String msg = jsonObject.getString("message");
        log.info("服务端收到客户端消息 ==> fromname = {}, toname = {}, message = {}", name, toname, message);

        /**
         * 模拟约定：如果未指定name信息，则群发，否则就单独发送
         */
        if (toname == null || toname == "" || "".equalsIgnoreCase(toname)) {
            sendToAll(msg);
        } else {
            sendToOne(toname, msg);
        }
    }

    /**
     * 发生错误调用的方法
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("WebSocket发生错误，错误信息为：" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 群发消息
     *
     * @param message 消息
     */
    private void sendToAll(String message) {
        // 遍历在线map集合
        onlineSessionClientMap.forEach((onlineName, toSession) -> {
            // 排除掉自己
            if (!name.equalsIgnoreCase(onlineName)) {
                log.info("服务端给客户端群发消息 ==> name = {}, toname = {}, message = {}", name, onlineName, message);
                MessageVo messageVo = new MessageVo();
                messageVo.setFrom(name);
                messageVo.setDate(new Date());
                messageVo.setMessage(message);
                toSession.getAsyncRemote().sendText(JSON.toJSONString(messageVo));
            }
        });
    }

    /**
     * 指定发送消息
     *
     * @param toName
     * @param message
     */
    private void sendToOne(String toName, String message) {
        // 通过name查询map中是否存在
        Session toSession = onlineSessionClientMap.get(toName);
        if (toSession == null) {
            log.error("服务端给客户端发送消息 ==> toname = {} 不存在, message = {}", toName, message);
            return;
        }
        // 异步发送
        log.info("服务端给客户端发送消息 ==> toname = {}, message = {}", toName, message);
        MessageVo messageVo = new MessageVo();
        messageVo.setFrom(name);
        messageVo.setDate(new Date());
        messageVo.setMessage(message);
        toSession.getAsyncRemote().sendText(JSON.toJSONString(messageVo));

    }

}

